#ifndef BHXJASYNWORKER_H
#define BHXJASYNWORKER_H
#include"functional"
#include"thread"
#include"mutex"
#include"queue"
#include"condition_variable"
#include"BHXJControls_global.h"
#include"iostream"
#include"sstream"
#include"string"
using namespace std;
class BHXJCONTROLS_EXPORT BHXJAsynWorker
{
    using Task=std::function<void()>;
public:
    BHXJAsynWorker();
    virtual ~BHXJAsynWorker();
    template<class F, class... Args>
    void BeginInvoke1(F&& fun,Args&&... args)
    {
        using rtype = decltype(fun(args...));
        auto bindfun=make_shared<function<rtype()>>(bind(forward<F>(fun), forward<Args>(args)...));

        lock_guard<mutex> lock{_lock};
        _tasks.emplace([bindfun]()
        {
            rtype r=(*bindfun)();
        });
    }
    template<class F,class C, class... Args>
    void BeginInvoke2(F&& fun,C&& callback,Args&&... args)
    {
        using rtype = decltype(fun(args...));

        auto bindfun=make_shared<function<rtype()>>(bind(forward<F>(fun), forward<Args>(args)...));
        auto cb=make_shared<function<void(rtype)>>(forward<C>(callback));
        //auto bindfun=(bind(std::forward<F>(fun), std::forward<Args>(args)...));
        //auto cb=std::forward<C>(callback);

        lock_guard<mutex> lock{_lock};
        _tasks.emplace([bindfun,cb]()
        {
            rtype r=(*bindfun)();
            (*cb)(r);
        });
        _task_cv.notify_one();
    }

protected:
    std::queue<Task> _tasks;
    thread *workthread;
    condition_variable _task_cv;
    bool _run=true;
    mutex _lock;
};

#endif // BHXJASYNWORKER_H
